﻿<title>Simple client-side WebRTC Experiment using WebSocket over PubNub ® Muaz Khan</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

<h1>Simple client-side WebRTC Experiment using WebSocket over PubNub</h1>

<blockquote style="background: #f3b7b7;border: 5px solid black;border-radius: 5px;padding: 5px 10px; margin: 10px 20px;">
    This demo is <span style="border: 1px dotted red; background: yellow; padding: 2px 5px;">out-dated (published on 2013)</span>. Please check this instead: <a href="https://github.com/webrtc/samples">https://github.com/webrtc/samples</a>
</blockquote>

<meta name="description" content="A client side WebRTC experiment/demo using WebSocket over PubNub! It is simple. It is included here for newcomers who are interested to learn WebRTC from demos!">
<link rel="author" type="text/html" href="https://plus.google.com/100325991024054712503">
<meta name="author" content="Muaz Khan">

<style>@font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 300; src: local('Open Sans Light'), local('OpenSans-Light'), url(/images/font.woff) format('woff'); } html { background: #ECECEC; font-family: 'Open Sans'; } body { color: #333; font: 1.4em 'Open Sans' , arial, sans-serif; font-weight: 300; line-height: 1.5; margin: 0 3em; background: white; border: 1px dotted #BBA9A9; border-top: 0; } h1, h2 { color: #2778ec; font-size: 1.6em; font-weight: 300; line-height: 1.15; }  a { display: inline-block; padding: 0.2em; color: #1B75C9; text-decoration: none; border-bottom: 1px dotted #0085FF; margin: 0 .2em; } a:hover { color: red; }</style>

<div style="position: absolute;background: white;display: block; padding: 5px 10px;z-index: 100;">
    <a href="/">Home</a>
    » <a href="https://github.com/muaz-khan/WebRTC-Experiment/blob/master/demos/client-side-websocket.html">Source Code</a>
</div>

<script>
    function uniqueToken() {
        var s4 = function () {
            return Math.floor(Math.random() * 0x10000).toString(16);
        };
        return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
    }
    var uniqueChannel = uniqueToken();
</script>

<script src="/lib/RTCPeerConnection-v1.4.js"></script>
<script src="/dependencies/websocket.js"></script>

<style>body{text-align: center;}</style>
<h2>Client video</h2>
<video id="client-video" autoplay></video>

<h2>Remote video / Getting stream from peer2</h2>
<video id="remote-video-1" autoplay></video>

<h2>Remote video / Getting stream from peer1</h2>
<video id="remote-video-2" autoplay></video>

<!-- First of all; get camera -->
<script>
    var socket;
	var pub = 'pub-c-3c0fc243-9892-4858-aa38-1445e58b4ecb';
    var sub = 'sub-c-d0c386c6-7263-11e2-8b02-12313f022c90';
    function openSocket() {
        socket = new WebSocket('wss://pubsub.pubnub.com/'+ pub +'/'+ sub +'/' + uniqueChannel);

        socket.onmessage = function (event) {
            var message = event.data;

            if (message.firstPart || message.secondPart || message.thirdPart) {
                if (message.firstPart) {
                    global.firstPart = message.firstPart;
                    if (global.secondPart && global.thirdPart) processReceievdSDP(message.by);
                }
                if (message.secondPart) {
                    global.secondPart = message.secondPart;
                    if (global.firstPart && global.thirdPart) processReceievdSDP(message.by);
                }

                if (message.thirdPart) {
                    global.thirdPart = message.thirdPart;
                    if (global.firstPart && global.secondPart) processReceievdSDP(message.by);
                }
            }

            if (message.candidate) {
                /* 2nd peer should process/add ice candidates sent by 1st peer! */
                if (message.by == 'peer1') {
                    peer2 && peer2.addICE({
                        sdpMLineIndex: message.sdpMLineIndex,
                        candidate: JSON.parse(message.candidate)
                    });
                }
                else {
                    peer1 && peer1.addICE({
                        sdpMLineIndex: message.sdpMLineIndex,
                        candidate: JSON.parse(message.candidate)
                    });
                }
            }
        };
        socket.onopen = function () {
            /* Socket opened; Now start creating offer sdp */
            create1stPeer();
        };
    }
	
	function processReceievdSDP(by)
	{
		if (by == 'peer1') {
			offerSDP = JSON.parse(global.firstPart + global.secondPart + global.thirdPart);
			setTimeout(create2ndPeer, 400);
		}
		
		/* 1st peer should complete the handshake using answer SDP provided by 2nd peer! */
		else peer1.addAnswerSDP(JSON.parse(global.firstPart + global.secondPart + global.thirdPart));
	}

    getUserMedia({
        video: document.getElementById('client-video'),
        onsuccess: function (stream) {
            clientStream = stream;

            openSocket();
        },
        onerror: function () {
            alert('Either you not allowed access to your microphone/webcam or another application already using it.');
        }
    });
    
    var clientStream;

    var global = {};
</script>

<!-- First peer: the offerer -->
<script>
    /* "offerSDP" will be used by your participant! */
    var offerSDP, peer1;

    function create1stPeer() {
        var offerConfig = {
            onOfferSDP: function (sdp) {
                console.log('1st peer: offer sdp: ' + sdp);

                /* Transmit offer SDP toward 2nd peer */
                sendsdp(sdp, 'peer1');
            },
            onICE: function (candidate) {
                console.log('1st peer: candidate' + candidate);

                socket.send({
                    by: 'peer1',
                    sdpMLineIndex: candidate.sdpMLineIndex,
                    candidate: JSON.stringify(candidate.candidate)
                });
            },
            onRemoteStream: function (stream) {
                console.log('1st peer: Wow! Got remote stream!');
                
				var video = document.getElementById('remote-video-1');
				if (!navigator.mozGetUserMedia) video.src = URL.createObjectURL(stream);
				else video.mozSrcObject = stream;
				video.play();
            },
            attachStream: clientStream
        };

        peer1 = RTCPeerConnection(offerConfig);
    }
</script>

<!-- Second peer: the participant -->
<script>

    var peer2;

    function  create2ndPeer() {
        var answerConfig = {
            onAnswerSDP: function (sdp) {
                console.log('2nd peer: sdp' + sdp);

                /* Transmit answer SDP toward 1st peer */
                sendsdp(sdp, 'peer2');
            },
            onICE: function (candidate) {
                console.log('2nd peer: candidate' + candidate);

                socket.send({
                    by: 'peer2',
                    sdpMLineIndex: candidate.sdpMLineIndex,
                    candidate: JSON.stringify(candidate.candidate)
                });
            },
            onRemoteStream: function (stream) {
                console.log('2nd peer: Wow! Got remote stream!');
                var video = document.getElementById('remote-video-2');
				if (!navigator.mozGetUserMedia) video.src = URL.createObjectURL(stream);
				else video.mozSrcObject = stream;
				video.play();
            },
            attachStream: clientStream,

            /* You'll use offer SDP here */
            offerSDP: offerSDP
        };
        peer2 = RTCPeerConnection(answerConfig);
    }

    function sendsdp(sdp, by) {
        sdp = JSON.stringify(sdp);
            var part = parseInt(sdp.length / 3);

            var firstPart = sdp.slice(0, part),
                secondPart = sdp.slice(part, sdp.length - 1),
                thirdPart = '';

            if (sdp.length > part + part) {
                secondPart = sdp.slice(part, part + part);
                thirdPart = sdp.slice(part + part, sdp.length);
            }

            socket.send({
                by: by,
                firstPart: firstPart
            });

            socket.send({
                by: by,
                secondPart: secondPart
            });

            socket.send({
                by: by,
                thirdPart: thirdPart
            });
    }
</script>